﻿using Microsoft.Practices.Unity;
using Sasa.QualityTools.CodeAnalysis.Core.Utilities;
using Sasa.QualityTools.CodeAnalysis.Core.VisualStudio;
using Sasa.QualityTools.CodeAnalysis.FxCopIntegrator.ViewModels;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;


namespace Sasa.QualityTools.CodeAnalysis.FxCopIntegrator.Commands.Behaviors.CodeAnalysis.Metrics
{
    public class ShowCodeMetricsCalculationResultBehavior : ICommandBehavior<CodeAnalysisCommandExecutionContext>
    {
        private IUnityContainer container;


        public ShowCodeMetricsCalculationResultBehavior(IUnityContainer container)
        {
            this.container = container;
        }


        public void Behave(CodeAnalysisCommandExecutionContext context)
        {
            if (context.Progress.Status != CodeAnalysisStatus.Completed)
            {
                return;
            }

            var ide = container.Resolve<IIde>();

            var model = BuildupCodeMetricsCalculationResult(context.Progress.CodeAnalyzers.OfType<CodeMetricsCalculatorViewModel>());
            var view = ide.FindCodeMetricsCalculationResultView();
            view.DataContext = model;
            view.Show();

            model.GoToFirstPage();
            model.Sort("MaintainabilityIndex");
            model.ClearHistories();
        }

        private CodeMetricsCalculationResultViewModel BuildupCodeMetricsCalculationResult(IEnumerable<CodeMetricsCalculatorViewModel> calculators)
        {
            var model = new CodeMetricsCalculationResultViewModel();

            var ide = container.Resolve<IIde>();
            var mapping = ide.Solution.GetBuildTargetProjects(false)
                .Where(o => o.IsSupportedCodeAnalysis)
                .ToDictionary(o => o.AssemblyPath);

            foreach (var calculator in calculators)
            {
                foreach (var metricCalue in calculator.MetricValues)
                {
                    if (metricCalue.AssemblyPath != null && mapping.ContainsKey(metricCalue.AssemblyPath))
                    {
                        var prj = mapping[metricCalue.AssemblyPath];
                        metricCalue.ProjectName = prj.Name;
                        if (metricCalue.Path == null && metricCalue.TypeName != null)
                        {
                            metricCalue.Path = prj.GetFilePathFromTypeName(metricCalue.TypeName);
                        }
                    }
                    model.Rows.Add(metricCalue);
                }
            }

            model.CodeFocusRequested += (sender, e) =>
            {
                if (e.Path != null)
                {
                    ide.Solution.Open(e.Path, e.Line);
                }
            };
            model.ExportReportRequired += (sender, e) =>
            {
                using (var dialog = new SaveFileDialog())
                {
                    dialog.Title = "Export Code Metrics Calculation Result Report";
                    dialog.DefaultExt = "csv";
                    dialog.Filter = "CSV File (*.csv)|*csv";
                    if (dialog.ShowDialog() == DialogResult.OK)
                    {
                        var generator = new ReportGenerator<MetricValueViewModel>();
                        generator.RegisterColumn("Project", o => o.ProjectName);
                        generator.RegisterColumn("Kind", o => o.Kind);
                        generator.RegisterColumn("Assembly", o => o.AssemblyName);
                        generator.RegisterColumn("Namespace", o => o.Namespace);
                        generator.RegisterColumn("Type", o => o.TypeName);
                        generator.RegisterColumn("Signature", o => o.Signature);
                        generator.RegisterColumn("Maintainability Index", o => o.MaintainabilityIndex.ToString());
                        generator.RegisterColumn("Cyclomatic Complexity", o => o.CyclomaticComplexity.ToString());
                        generator.RegisterColumn("Class Coupling", o => o.ClassCoupling.ToString());
                        generator.RegisterColumn("Lines of Code", o => o.LinesOfCode.ToString());
                        generator.RegisterColumn("Depth Of Inheritance", o => (o.DepthOfInheritance.HasValue) ? o.DepthOfInheritance.ToString() : "");
                        generator.RegisterColumn("Path", o => o.Path);
                        generator.RegisterColumn("Line", o => (o.Line.HasValue) ? o.Line.ToString() : "");
                        generator.Generate(dialog.FileName, model.Rows);
                        ide.NotifyInfo("Exported code metrics calculation result.");
                    }
                }
            };
            model.GoToHowToSearchPageRequired += (sender, e) =>
            {
                ide.Navigate("http://fxcopintegrator.codeplex.com/wikipage?title=Search%20Code%20Metrics%20Calculation%20Result");
            };

            return model;
        }
    }
}
